home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d1 / clipasc.arc / CLIPASC.ASM < prev    next >
Assembly Source File  |  1987-03-17  |  24KB  |  1,070 lines

  1. ;----------------------------------------------------------------
  2. ;    CLIPASC - ASCII file access from Clipper. W85 or later
  3. ;          required.
  4. ; Description:
  5. ;    CLIPASC is a set of functions which allow Clipper to
  6. ;    open and manipulate flat ASCII files rather than needing
  7. ;    to convert them to dBASE format first.
  8. ; Language:
  9. ;    CLIPASC was written using Microsoft(C) Macro Assembler
  10. ;    version 4.0
  11. ; Version:
  12. ;    Version 1.1 - 2/26/87
  13. ; Author:
  14. ;    Ben Cohen
  15. ;    12 Britton St.
  16. ;    Jersey City, NJ  07306
  17. ; Change History:
  18. ;    v1.1 - Fix _retxx calls so that they restore ES and BP
  19. ;           before call.
  20. ;         - Change combine class of code seg to 'PROG' to
  21. ;           hide it in Clipper's code.
  22. ;----------------------------------------------------------------
  23.  
  24.     include ascscan.mac
  25.  
  26.  
  27. dgroup    group    dataseg
  28.  
  29.  
  30. dataseg segment public 'DATA'
  31.  
  32.         db    'CLIPASC '      ; eye-grabber
  33.  
  34. clip_save_es    dw    ?        ; save area for ES
  35.  
  36. last_ret_cd    dw    ?        ; return codes - retrieved by ASCRETCD
  37.  
  38. null_str    db    00h,00h
  39.  
  40. ;------ Data for OPENASC
  41.  
  42. open_parms    dw    2,character,character
  43.  
  44. openasc_flags    db    ?        ; flag byte
  45. open_mode    db    4 dup (?)    ; mode to use for opening
  46. openasc_tname    db    128 dup (?)    ; temp space for name
  47.  
  48. ;------ Data for CLOSEASC
  49.  
  50. close_parms    dw    1,numeric
  51.  
  52. ;------ Data for LINEIN
  53.  
  54. linein_parms    dw    1,numeric
  55.  
  56. linein_handle    dw    ?
  57. linein_high    dw    ?
  58. linein_low    dw    ?
  59.  
  60. linein_buf    db    512 dup (?)
  61.         db    00h
  62.  
  63. ;------ Data for LINEOUT
  64.  
  65. lineout_parms    dw    2,numeric,character
  66.  
  67. lineout_handle    dw    ?
  68. lineout_buf    db    512 dup (?)
  69.         db    0d,0ah        ; just in case it's that long
  70.  
  71. ;------ Data for CHARIN
  72.  
  73. charin_parms    dw    2,numeric,numeric+optional
  74.  
  75. charin_handle    dw    ?
  76.  
  77. ;------ Data for CHAROUT
  78.  
  79. charout_parms    dw    2,numeric,character+optional
  80.  
  81. charout_handle    dw    ?
  82.  
  83. ;------ Data for ASCLSEEK
  84.  
  85. asclseek_parms    dw    3,numeric,character+optional,numeric+optional
  86.  
  87. asclseek_handle dw    ?
  88. asclseek_method db    ?
  89. asclseek_high    dw    ?
  90. asclseek_low    dw    ?
  91.  
  92. dataseg ends
  93.  
  94.  
  95. clipasc segment public 'PROG'
  96.  
  97.     public    openasc
  98.     public    closeasc
  99.     public    ascretcd
  100.     public    linein
  101.     public    charin
  102.     public    lineout
  103.     public    charout
  104.     public    asclseek
  105.  
  106.     assume    cs:clipasc,ds:dgroup
  107.  
  108. err_dos_base    equ    4096        ; base errcode for a DOS errcode '0'
  109. err_inv_parms    equ    8192        ; errcode for invalid # of parms
  110. err_parms_base    equ    8200        ; base errcode for invalid parm # 0
  111.  
  112. ;----------------------------------------------------------------
  113. ;    OPENASC
  114. ; Description:
  115. ;    Using passed info, open ASCII file in read,
  116. ;    write, or read/write mode and then, possibly
  117. ;    position the pointer to end of file for
  118. ;    appending.
  119. ; Input:
  120. ;    _par(0)  = 2
  121. ;    _parc(1) = fully qualified file name and ext.
  122. ;    _parc(2) = 'r'   - read mode, beginning
  123. ;           'w'   - write mode, create file, beginning
  124. ;           'rw'  - read/write mode, beginning, create if non-existant
  125. ;           'w+'  - write mode, append to file, end of file
  126. ;           'rw+' - read/write mode, appending, end of file
  127. ; Returns:
  128. ;    _retni() = file handle if ok
  129. ;           -1 if error, error code available with ASCRETCD
  130. ;----------------------------------------------------------------
  131.  
  132. err_inv_mode    equ    8301        ; Invalid access mode
  133.  
  134. open_jump_end    equ    0001h        ; jump to end of file
  135. open_chk_file    equ    0002h        ; see if file exists - if not, create
  136.  
  137.     db    'CLIPASC '              ; eye-grabber
  138.  
  139. openasc proc    far
  140.     ifdef    debug
  141.     int    3
  142.     endif
  143.     push    bp
  144.     push    es
  145.     mov    bp,sp
  146.  
  147.     cld                ; forward, please
  148.  
  149. ;------ Check that parms are ok
  150.  
  151.     parm_chk    dgroup:open_parms,openasc_ret_bad
  152.  
  153. ;------ Now lets get the info
  154.  
  155.     mov    clip_save_es,es     ; save ES for future
  156.  
  157.     get_char    2
  158.  
  159.     mov    es,ax            ; get segment
  160.     mov    si,bx            ; get offset
  161.     mov    di,offset dgroup:open_mode    ; where to put it
  162.  
  163. openasc_copy_mode:
  164.     mov    al,es:[si]        ; get next character
  165.     or    al,al            ; is it zero yet?
  166.     jz    openasc_mode_done
  167.     mov    ds:[di],al        ; save the character
  168.     inc    si            ; next character position
  169.     inc    di
  170.     jmp    openasc_copy_mode    ; next character
  171.  
  172. openasc_mode_done:
  173.     mov    ds:[di],al        ; store the final 00h
  174.  
  175.     mov    al,00h
  176.     mov    openasc_flags,al
  177.  
  178.     mov    si,offset dgroup:open_mode
  179.     lodsb                ; get first character of mode
  180.     cmp    al,'r'                  ; read (partial or only)?
  181.     je    openasc_reads
  182.     cmp    al,'w'                  ; better be write, then.
  183.     je    openasc_writes
  184.  
  185.     mov    ax,err_inv_mode     ; nope, time to go
  186.     jmp    openasc_ret_bad
  187.  
  188. ;------ Write modes, check for '+' and make sure nothing else
  189.  
  190. openasc_writes:
  191.     lodsb                ; check next byte
  192.     cmp    al,00h            ; write only?
  193.     je    openasc_create        ; yup, create the file
  194.  
  195.     cmp    al,'+'                  ; append?
  196.     je    openasc_wrt_apd     ; yup
  197.  
  198.     mov    ax,err_inv_mode     ; bad mode
  199.     jmp    openasc_ret_bad
  200.  
  201. ;------ Read or read/write modes, still have to check
  202.  
  203. openasc_reads:
  204.     lodsb
  205.     cmp    al,00h            ; read only?
  206.     je    openasc_read        ; yup
  207.  
  208.     cmp    al,'w'                  ; better be read/write
  209.     je    openasc_rw        ; yup, check for appending
  210.  
  211.     mov    ax,err_inv_mode
  212.     jmp    openasc_ret_bad
  213.  
  214. ;------ Read/write mode. Have to check for appending
  215.  
  216. openasc_rw:
  217.     lodsb                ; next character
  218.     cmp    al,00h            ; read/write at beginning?
  219.     je    openasc_rd_wrt        ; yup
  220.  
  221.     cmp    al,'+'                  ; appending also?
  222.     je    openasc_rw_apd        ; yup
  223.  
  224.     mov    ax,err_inv_mode     ; bad mode
  225.     jmp    openasc_ret_bad
  226.  
  227. ;------ Have to create the file
  228.  
  229. openasc_create:
  230.     mov    ah,03ch         ; create function (DOS)
  231.     mov    cx,0000h        ; no attributes
  232.     jmp    openasc_common
  233.  
  234. ;------ Appending to existing file
  235.  
  236. openasc_wrt_apd:
  237.     lodsb                ; that better have been it
  238.     cmp    al,00h            ; check to make sure
  239.     je    open_wrt_apd_1        ; yeah, it's ok
  240.  
  241.     mov    ax,err_inv_mode     ; bad mode
  242.     jmp    openasc_ret_bad
  243.  
  244. open_wrt_apd_1:
  245.     or    openasc_flags,open_chk_file+open_jump_end
  246.                     ; needs to be there and we want to be
  247.                     ;  at the end
  248.     mov    ah,03dh         ; open file (DOS)
  249.     mov    al,00010001b        ; access mode flags (exclusive)
  250.     jmp    openasc_common
  251.  
  252. ;------ Read only file
  253.  
  254. openasc_read:
  255.     mov    ah,03dh         ; open file (DOS)
  256.     mov    al,01000000b        ; access mode flags
  257.     jmp    openasc_common
  258.  
  259. ;------ Read/write access at beginning
  260.  
  261. openasc_rd_wrt:
  262.     mov    ah,03dh         ; open file (DOS)
  263.     mov    al,00010010b        ; access mode flags (exclusive)
  264.     jmp    openasc_common
  265.  
  266. ;------ Read/write with appending
  267.  
  268. openasc_rw_apd:
  269.     lodsb                ; make sure string ends
  270.     cmp    al,00h            ; check to make sure
  271.     je    open_rw_apd_1        ; yup, ok
  272.  
  273.     mov    ax,err_inv_mode     ; bad mode
  274.     jmp    openasc_ret_bad
  275.  
  276. open_rw_apd_1:
  277.     or    openasc_flags,open_chk_file+open_jump_end
  278.                     ; needs to be there and we want to be
  279.                     ;  at the end
  280.     mov    ah,03dh         ; open file (DOS)
  281.     mov    al,00010010b        ; access mode flags (exclusive)
  282.     jmp    openasc_common
  283.  
  284. ;------ Common code for all opening types
  285.  
  286. openasc_common:
  287.     mov    es,clip_save_es
  288.     push    ax            ; save important regs
  289.     push    cx
  290.  
  291.     get_char    1        ; get pointer to name.ext
  292.     mov    cx,ds            ; set ES = DS
  293.     mov    es,cx
  294.     mov    di,offset dgroup:openasc_tname
  295.     mov    dx,di            ; save it for later
  296.     mov    ds,ax
  297.     mov    si,bx
  298.     mov    cx,128            ; max ASCIIZ string len
  299.  
  300.     rep    movsb            ; don't care if we get extra
  301.  
  302.     mov    ax,es            ; restore DS
  303.     mov    ds,ax
  304.     mov    es,clip_save_es     ; restore ES
  305.  
  306. ;------ Let's make a first crack at it
  307.  
  308.     pop    cx            ; restore important regs
  309.     pop    ax
  310.  
  311.     int    21h            ; go do it
  312.  
  313.     jnc    openasc_openok
  314.     test    openasc_flags,open_chk_file    ; make it if it's not there?
  315.     jnz    openasc_chk_ocd
  316.  
  317.     add    ax,err_dos_base     ; give them the code
  318.     jmp    openasc_ret_bad
  319.  
  320. ;------ Check opening code and see if we got 'file not found' when we should
  321.  
  322. openasc_chk_ocd:
  323.     cmp    ax,2            ; file not found?
  324.     je    openasc_crtit        ; yeah, create it
  325.  
  326.     add    ax,err_dos_base     ; give them the code
  327.     jmp    openasc_ret_bad
  328.  
  329. openasc_crtit:
  330.     mov    ah,03ch         ; create file (DOS)
  331.     mov    cx,0000h        ; no attributes
  332.     mov    dx,offset dgroup:openasc_tname    ; get name
  333.     int    21h            ; create it now
  334.  
  335.     jnc    openasc_openok        ; good create
  336.  
  337.     add    ax,err_dos_base
  338.     jmp    openasc_ret_bad
  339.  
  340. ;------ Got good opening. Check for jump to end
  341.  
  342. openasc_openok:
  343.     test    openasc_flags,open_jump_end
  344.     jz    openasc_ret_gd
  345.  
  346.     push    ax            ; save handle
  347.     mov    bx,ax            ; get handle in right reg
  348.     mov    ah,042h         ; LSEEK (DOS)
  349.     xor    cx,cx            ; don't want to move it
  350.     xor    dx,dx
  351.     mov    al,2            ; except to the end
  352.  
  353.     int    21h            ; go do it
  354.  
  355.     jc    openasc_fail_seek
  356.     pop    ax            ; get handle
  357.     jmp    openasc_ret_gd
  358.  
  359. openasc_fail_seek:
  360.     add    ax,err_dos_base
  361.     jmp    openasc_ret_bad
  362.  
  363. openasc_ret_gd:
  364.     push    ax
  365.     xor    ax,ax            ; want 0 return code
  366.     mov    last_ret_cd,ax
  367.     pop    ax
  368.     jmp    short openasc_ret
  369.  
  370. ;------ Have retcode in AX, set return number to -1 and save retcode
  371.  
  372. openasc_ret_bad:
  373.     mov    last_ret_cd,ax
  374.     xor    ax,ax
  375.     dec    ax
  376.     jmp    short openasc_ret
  377.  
  378. openasc_ret:
  379.     mov    es,clip_save_es
  380.     mov    sp,bp
  381.     pop    es
  382.     pop    bp
  383.     ret_int ax
  384.     ret
  385. openasc endp
  386.  
  387.  
  388. ;----------------------------------------------------------------
  389. ;    ASCRETCD
  390. ; Description:
  391. ;    This procedure will return the real return code from the
  392. ;    previously called function. This is to permit returning
  393. ;    of an error code for those functions that can only take
  394. ;    a character string as a return value.
  395. ; Input:
  396. ;    None
  397. ; Output:
  398. ;    _retni() = last return code for ASCII functions.
  399. ;----------------------------------------------------------------
  400.  
  401. ascretcd    proc    far
  402.     mov    ax,last_ret_cd
  403.     ret_int ax
  404.     ret
  405. ascretcd    endp
  406.  
  407.  
  408. ;----------------------------------------------------------------
  409. ;    CLOSEASC
  410. ; Description
  411. ;    This procedure will close an ASCII file based on the file
  412. ;    handle that is passed to it.
  413. ; Input:
  414. ;    _par(0)   = 1
  415. ;    _parni(1) = file handle to close
  416. ; Output:
  417. ;    _retni()  = 0 if close ok
  418. ;            -1 if error, error code accessible by ASCRETCD
  419. ;----------------------------------------------------------------
  420.  
  421. closeasc    proc    far
  422.     ifdef    debug
  423.     int    3
  424.     endif
  425.     push    bp
  426.     push    es
  427.     mov    bp,sp
  428.  
  429.     cld                ; forward, please
  430.  
  431.     parm_chk    dgroup:close_parms,closeasc_ret_bad
  432.  
  433.     get_int 1            ; get the file handle
  434.  
  435.     mov    bx,ax            ; into correct reg
  436.     mov    ah,03eh         ; close file (DOS)
  437.     int    21h            ; go do it
  438.  
  439.     jnc    closeasc_ret_gd
  440.  
  441.     add    ax,err_dos_base
  442.     jmp    closeasc_ret_bad
  443.  
  444. closeasc_ret_gd:
  445.     xor    ax,ax
  446.     mov    last_ret_cd,ax
  447.     jmp    short closeasc_ret
  448.  
  449. closeasc_ret_bad:
  450.     mov    last_ret_cd,ax
  451.     xor    ax,ax
  452.     dec    ax
  453.     jmp    short closeasc_ret
  454.  
  455. closeasc_ret:
  456.     mov    sp,bp
  457.     pop    es
  458.     pop    bp
  459.     ret_int ax
  460.     ret
  461. closeasc    endp
  462.  
  463.  
  464. ;----------------------------------------------------------------
  465. ;    LINEIN
  466. ; Description:
  467. ;    This procedure will read in a line of text from a flat
  468. ;    ASCII file, truncate CRLF and return the line to the
  469. ;    parent routine.
  470. ; Input:
  471. ;    _par(0)   = 1
  472. ;    _parni(1) = file handle to read from
  473. ; Output:
  474. ;    _retc()   = line returned. If len(line) = 0, return code
  475. ;            from ASCRETCD should be checked for error
  476. ;            condition. Return code = -1 if EOF reached.
  477. ;----------------------------------------------------------------
  478.  
  479. err_too_long    equ    8400        ; line > 512 bytes
  480.  
  481. linein    proc    far
  482.     ifdef    debug
  483.     int    3
  484.     endif
  485.     push    bp
  486.     push    es
  487.     mov    bp,sp
  488.     mov    clip_save_es,es
  489.  
  490.     cld                ; forward, please
  491.  
  492. ;------ Check our parameters
  493.  
  494.     parm_chk    dgroup:linein_parms,linein_ret_bad
  495.  
  496. ;------ Ok, now let's find out what's going on...
  497.  
  498.     get_int 1            ; get file handle
  499.  
  500.     mov    bx,ax            ; put in right reg
  501.     mov    linein_handle,bx
  502.     mov    ah,042h         ; LSEEK (DOS)
  503.     xor    cx,cx            ; no movement
  504.     xor    dx,dx
  505.     mov    al,1            ; move from current
  506.     int    21h
  507.  
  508.     jnc    linein_savcnt
  509.  
  510.     add    ax,err_dos_base     ; error of some kind
  511.     jmp    linein_ret_bad
  512.  
  513. ;------ Save the pointer location. It's important
  514.  
  515. linein_savcnt:
  516.     mov    linein_high,dx        ; save old file pointers
  517.     mov    linein_low,ax
  518.  
  519.     mov    ah,03fh         ; read file (DOS)
  520.     mov    bx,linein_handle    ; get handle
  521.     mov    dx,offset dgroup:linein_buf    ; get loc of buf
  522.     mov    cx,size linein_buf    ; get length of buf
  523.     int    21h            ; go do it
  524.  
  525.     jnc    linein_count
  526.  
  527.     add    ax,err_dos_base     ; error code
  528.     jmp    linein_ret_bad
  529.  
  530. ;------ Did we hit EOF?
  531.  
  532. linein_count:
  533.     cmp    ax,0000         ; are we at eof?
  534.     jne    linein_scan
  535.  
  536.     xor    ax,ax
  537.     dec    ax
  538.     jmp    linein_ret_bad        ; it's not an error, persay, but the
  539.                     ;  results are the same
  540.  
  541. ;------ Scan for EOF/CRLF combinations.
  542.  
  543. linein_scan:
  544.     mov    si,offset dgroup:linein_buf    ; get start of buffer
  545.     mov    al,00
  546.  
  547.     mov    cx,size linein_buf
  548. linein_scan_1:
  549.     mov    ah,al            ; save last character
  550.     lodsb
  551.     cmp    ax,0d0ah        ; check for CRLF
  552.     je    linein_crlf
  553.     cmp    al,01ah         ; check for EOF
  554.     je    linein_eof
  555.     loop    linein_scan_1
  556.  
  557.     mov    ax,err_too_long
  558.     jmp    linein_ret_gd
  559.  
  560. ;------ Handle a CRLF sequence in file
  561.  
  562. linein_crlf:
  563.     push    si            ; save our current loc
  564.     sub    si,2            ; don't count CRLF
  565.     mov    byte ptr ds:[si],00h    ; end of string
  566.     pop    si            ; get # of bytes read
  567.     sub    si,offset dgroup:linein_buf
  568.     mov    cx,linein_high        ; restore pointers
  569.     mov    dx,linein_low
  570.     add    dx,si            ; add number of bytes read
  571.     adc    cx,0
  572.  
  573.     mov    ah,042h         ; LSEEK (DOS)
  574.     mov    al,0            ; from beginning of file
  575.     mov    bx,linein_handle    ; get file handle
  576.     int    21h
  577.  
  578.     jnc    linein_finish        ; ok, now just clean up
  579.  
  580.     add    ax,err_dos_base
  581.     jmp    linein_ret_bad
  582.  
  583. ;------ Handle stumbling across EOF in file
  584.  
  585. linein_eof:
  586.     xor    ax,ax
  587.     dec    ax            ; -1 for EOF
  588.     jmp    linein_ret_bad        ; bad type handling
  589.  
  590. ;------ Clean up...
  591.  
  592. linein_finish:
  593.     xor    ax,ax
  594.     jmp    linein_ret_gd
  595.  
  596. linein_ret_gd:
  597.     mov    last_ret_cd,ax
  598.     mov    ax,dgroup
  599.     mov    bx,offset dgroup:linein_buf
  600.     jmp    short linein_ret
  601.  
  602. linein_ret_bad:
  603.     mov    last_ret_cd,ax
  604.     mov    ax,dgroup
  605.     mov    bx,offset dgroup:null_str
  606.     jmp    short linein_ret
  607.  
  608. linein_ret:
  609.     mov    es,clip_save_es
  610.     mov    sp,bp
  611.     pop    es
  612.     pop    bp
  613.     ret_char    ax,bx
  614.     ret
  615. linein    endp
  616.  
  617.  
  618. ;----------------------------------------------------------------
  619. ;    LINEOUT
  620. ; Description:
  621. ;    This procedure will take the passed string and write it
  622. ;    out to the specified flat ASCII file.
  623. ; Input:
  624. ;    _par(0)   = 2
  625. ;    _parni(1) = file handle to write to
  626. ;    _parc(2)  = string to write. must be <= 512 bytes long.
  627. ; Output:
  628. ;    _retni()  = 0 if ok
  629. ;            -1 if error. Error code accessable by ASCRETCD
  630. ;----------------------------------------------------------------
  631.  
  632. lineout proc    far
  633.     ifdef    debug
  634.     int    3
  635.     endif
  636.     push    bp
  637.     push    es
  638.     mov    bp,sp
  639.     mov    clip_save_es,es
  640.  
  641.     cld                ; forward, please
  642.  
  643. ;------ Check our parameters
  644.  
  645.     parm_chk    dgroup:lineout_parms,lineout_ret_bad
  646.  
  647. ;------ Get info
  648.  
  649.     get_int 1            ; get the file handle
  650.  
  651.     mov    lineout_handle,ax    ; save it for later use
  652.  
  653.     get_char 2            ; get seg:off of string
  654.     push    ds            ; save seg regs for later
  655.     push    es
  656.  
  657.     mov    es,ax            ; get segment
  658.     mov    di,bx            ; get offset
  659.     push    di            ; save start of string
  660.     mov    al,00h            ; search for end of string
  661.     xor    cx,cx            ; count until found
  662.     dec    cx
  663.     repne    scasb            ; look for it
  664.  
  665.     not    cx            ; how many did we scan through
  666.     dec    cx            ; one too many - don't count 00h
  667.     pop    si            ; restore that to keep stack clean
  668.     cmp    cx,size lineout_buf    ; too big?
  669.     jle    lineout_copy_line    ; nope, keep goint
  670.  
  671. ;------ String is greater than buffer size
  672.  
  673.     pop    es            ; restore regs
  674.     pop    ds
  675.     mov    ax,err_too_long     ; give 'em something to think about
  676.     jmp    lineout_ret_bad
  677.  
  678. ;------ Have to copy the string over
  679.  
  680. lineout_copy_line:
  681.     mov    ax,es            ; DS = ES - set source to target
  682.     mov    ds,ax
  683.     mov    di,offset dgroup:lineout_buf
  684.     mov    dx,di            ; save location for later
  685.     pop    es            ; restore ES for copy
  686.     rep    movsb            ; copy string over
  687.  
  688.     mov    al,0dh            ; send out CR
  689.     stosb
  690.     mov    al,0ah            ; send out LF
  691.     stosb
  692.     sub    di,offset dgroup:lineout_buf
  693.     mov    cx,di            ; get number of bytes to write
  694.  
  695.     pop    ds            ; restore regs
  696.  
  697.     mov    ah,040h         ; write to a file (DOS)
  698.     mov    bx,lineout_handle
  699.     int    21h
  700.  
  701.     jnc    lineout_ret_gd
  702.  
  703.     add    ax,err_dos_base
  704.     jmp    lineout_ret_bad
  705.  
  706. lineout_ret_gd:
  707.     xor    ax,ax
  708.     mov    last_ret_cd,ax
  709.     jmp    short lineout_ret
  710.  
  711. lineout_ret_bad:
  712.     mov    last_ret_cd,ax
  713.     xor    ax,ax
  714.     dec    ax
  715.     jmp    short lineout_ret
  716.  
  717. lineout_ret:
  718.     mov    es,clip_save_es
  719.     mov    sp,bp
  720.     pop    es
  721.     pop    bp
  722.     ret_int ax
  723.     ret
  724. lineout endp
  725.  
  726.  
  727. ;----------------------------------------------------------------
  728. ;    CHARIN
  729. ; Description:
  730. ;    This procedure will read a specified number of bytes from
  731. ;    a passed file handle. There will be no translation of the
  732. ;    information read, whatsoever.
  733. ; Input:
  734. ;    _par(0)   = 1|2
  735. ;    _parni(1) = file handle to read from
  736. ;    _parni(2) = number of characters to read. must be <= 512
  737. ;               optional - defaults to 1 character
  738. ; Output:
  739. ;    _retc()   = characters read. If len(line) = 0, return
  740. ;            code from ASCRETCD should be checked for error
  741. ;            condition. Return code = -1 if EOF reached.
  742. ;----------------------------------------------------------------
  743. charin    proc    far
  744.     ifdef    debug
  745.     int    3
  746.     endif
  747.     push    bp
  748.     push    es
  749.     mov    bp,sp
  750.     mov    clip_save_es,es
  751.  
  752. ;------ Check parameters
  753.  
  754.     parm_chk    dgroup:charin_parms,charin_ret_bad
  755.  
  756. ;------ Get the file handle and other info
  757.  
  758.     get_int 1
  759.     mov    charin_handle,ax    ; save the handle
  760.  
  761.     get_ptype 2
  762.     cmp    ax,undef        ; did they tell us how many?
  763.     jne    charin_how_many
  764.  
  765.     mov    ax,1            ; default to 1 byte
  766.     jmp    charin_read        ; and go do it
  767.  
  768. charin_how_many:
  769.     get_int 2
  770.     cmp    ax,size linein_buf    ; using buffer from linein
  771.     jle    charin_read
  772.  
  773.     mov    ax,err_too_long
  774.     jmp    charin_ret_bad
  775.  
  776. charin_read:
  777.     mov    cx,ax            ; get count to use
  778.     mov    dx,offset dgroup:linein_buf
  779.     add    ax,dx
  780.     push    ax            ; save addr of next char for later
  781.     mov    ah,3fh            ; read from file (DOS)
  782.     mov    bx,charin_handle
  783.     int    21h
  784.  
  785.     pop    bx            ; restore addr to clean up stack
  786.     jnc    charin_check_eof
  787.  
  788.     add    ax,err_dos_base
  789.     jmp    charin_ret_bad
  790.  
  791. charin_check_eof:
  792.     or    ax,ax            ; check how many bytes read
  793.     jnz    charin_set_str        ; no, everything's ok
  794.  
  795.     xor    ax,ax
  796.     dec    ax            ; set -1 ret code for EOF
  797.     jmp    charin_ret_bad        ; same processing
  798.  
  799. charin_set_str:
  800.     mov    byte ptr ds:[bx],00h    ; 00h terminator
  801.     xor    ax,ax
  802.     jmp    charin_ret_gd
  803.  
  804. charin_ret_gd:
  805.     mov    last_ret_cd,ax
  806.     mov    ax,dgroup
  807.     mov    bx,offset dgroup:linein_buf
  808.     jmp    short charin_ret
  809.  
  810. charin_ret_bad:
  811.     mov    last_ret_cd,ax
  812.     mov    ax,dgroup
  813.     mov    bx,offset dgroup:null_str
  814.     jmp    short charin_ret
  815.  
  816. charin_ret:
  817.     mov    es,clip_save_es
  818.     mov    sp,bp
  819.     pop    es
  820.     pop    bp
  821.     ret_char    ax,bx
  822.     ret
  823. charin    endp
  824.  
  825.  
  826. ;----------------------------------------------------------------
  827. ;    CHAROUT
  828. ; Description:
  829. ;    This procedure will write out the character string which
  830. ;    was passed to it, or, if no character string was passed,
  831. ;    will truncate the specified file.
  832. ; Input:
  833. ;    _par(0)   = 1|2
  834. ;    _parni(1) = handle of file to write to
  835. ;    _parc(2)  = string to be written out
  836. ;               optional - if not given, truncates file
  837. ;               at current write pointer
  838. ; Output:
  839. ;    _retni()  = 0 if ok
  840. ;            -1 if error, retcode accessible with ASCRETCD
  841. ;----------------------------------------------------------------
  842. charout proc    far
  843.     ifdef    debug
  844.     int    3
  845.     endif
  846.     push    bp
  847.     push    es
  848.     mov    bp,sp
  849.     mov    clip_save_es,es
  850.  
  851. ;------ Get our parameters and check them
  852.  
  853.     parm_chk    dgroup:charout_parms,charout_ret_bad
  854.  
  855. ;------ Let's do something with our parameters
  856.  
  857.     get_int 1            ; get the file handle
  858.     mov    charout_handle,ax    ; and save it for later
  859.  
  860.     get_char 2            ; get what we have to write
  861.     mov    es,ax            ; get segment
  862.     mov    di,bx            ; get offset
  863.     mov    al,00h            ; find end of string
  864.     xor    cx,cx            ; do it until we find it
  865.     dec    cx
  866.     push    di            ; save start of string for later
  867.     repne    scasb            ; find it...
  868.  
  869.     not    cx            ; turn it positive
  870.     dec    cx            ; and don't count the 00h
  871.     pop    dx            ; need offset in DX
  872.     mov    bx,charout_handle    ; restore handle
  873.     push    ds
  874.     mov    ax,es
  875.     mov    ds,ax            ; need segment in DS
  876.     mov    ah,040h         ; write file (DOS)
  877.     int    21h            ; and go do it
  878.     pop    ds            ; restore dataseg before all else
  879.  
  880.     jnc    charout_ret_gd
  881.  
  882.     add    ax,err_dos_base
  883.     jmp    charout_ret_bad
  884.  
  885. charout_ret_gd:
  886.     xor    ax,ax
  887.     mov    last_ret_cd,ax
  888.     jmp    short charout_ret
  889.  
  890. charout_ret_bad:
  891.     mov    last_ret_cd,ax
  892.     xor    ax,ax
  893.     dec    ax
  894.     jmp    short charout_ret
  895.  
  896. charout_ret:
  897.     mov    es,clip_save_es
  898.     mov    sp,bp
  899.     pop    es
  900.     pop    bp
  901.     ret_int ax
  902.     ret
  903. charout endp
  904.  
  905.  
  906. ;----------------------------------------------------------------
  907. ;    ASCLSEEK
  908. ; Description:
  909. ;    This procedure implements the DOS LSEEK function which
  910. ;    allows positioning within a file.
  911. ; Input:
  912. ;    _par(0)   = 1|2|3
  913. ;    _parni(1) = file handle to work with
  914. ;    _parc(2)  = 'b'|'B' - offset from beginning of file
  915. ;            'c'|'C' - offset from current position in file
  916. ;            'e'|'E' - offset from end of file
  917. ;            if not given, defaults to 'c'
  918. ;    _parni(3) = length to move from location given in _parc(2)
  919. ;            if not given, defaults to 0
  920. ; Output:
  921. ;    _retnl()  = current pointer within file, or -1 if error
  922. ;            if error, retcode available from ASCRETCD
  923. ;----------------------------------------------------------------
  924.  
  925. err_bad_method    equ    8401
  926. err_bad_offset    equ    8402
  927.  
  928. ;------ Equates for pointer movement methods
  929.  
  930. offset_bof    equ    00h
  931. offset_cur    equ    01h
  932. offset_eof    equ    02h
  933.  
  934. asclseek    proc    far
  935.     ifdef    debug
  936.     int    3
  937.     endif
  938.     push    bp
  939.     push    es
  940.     mov    bp,sp
  941.     mov    clip_save_es,es
  942.  
  943. ;------ Check our parameters
  944.  
  945.     parm_chk    dgroup:asclseek_parms,asclseek_ret_bad
  946.  
  947. ;------ Start playing with them...
  948.  
  949.     get_int 1            ; get the file handle
  950.     mov    asclseek_handle,ax    ; and save it for later
  951.  
  952.     mov    al,offset_cur        ; default method
  953.     mov    asclseek_method,al    ; save it
  954.  
  955.     get_ptype 2            ; did they give us a method
  956.     cmp    ax,undef
  957.     jne    asclseek_parse_meth    ; go scan the method
  958.  
  959.     jmp    asclseek_get_offset
  960.  
  961. ;------ We've got a method. Find out what it is.
  962.  
  963. asclseek_parse_meth:
  964.     get_char 2            ; get the string
  965.     mov    es,ax            ; get segment
  966.     mov    di,bx            ; get offset
  967.  
  968.     mov    ax,es:[di]        ; get the string
  969.     mov    es,clip_save_es     ; restore ES immediately
  970.     cmp    ah,00h            ; only one character?
  971.     je    asclseek_chk_meth
  972.  
  973.     mov    ax,err_bad_method    ; set error code
  974.     jmp    asclseek_ret_bad
  975.  
  976. ;------ Got it. Now check against accepted ones.
  977.  
  978. asclseek_chk_meth:
  979.     or    al,'a'-'A'              ; to lower case
  980.     cmp    al,'c'                  ; Current pos?
  981.     jne    asclseek_chk_1
  982.     mov    al,offset_cur
  983.     jmp    asclseek_save_meth
  984.  
  985. asclseek_chk_1:
  986.     cmp    al,'b'                  ; Beginning of file
  987.     jne    asclseek_chk_2
  988.     mov    al,offset_bof
  989.     jmp    asclseek_save_meth
  990.  
  991. asclseek_chk_2:
  992.     cmp    al,'e'                  ; End of file
  993.     jne    asclseek_bad_meth
  994.     mov    al,offset_eof
  995.     jmp    asclseek_save_meth
  996.  
  997. asclseek_bad_meth:
  998.     mov    ax,err_bad_method    ; set error code
  999.     jmp    asclseek_ret_bad
  1000.  
  1001. asclseek_save_meth:
  1002.     mov    asclseek_method,al
  1003.  
  1004. ;------ Did they give us an offset to move?
  1005.  
  1006. asclseek_get_offset:
  1007.     xor    ax,ax
  1008.     mov    asclseek_high,ax    ; set defaults
  1009.     mov    asclseek_low,ax
  1010.  
  1011.     get_ptype 3            ; did they give us an offset?
  1012.     cmp    ax,undef
  1013.     jne    asclseek_chk_offset
  1014.  
  1015.     jmp    asclseek_move
  1016.  
  1017. ;------ Get what the offset is and do minimal checking
  1018.  
  1019. asclseek_chk_offset:
  1020.     get_long 3
  1021.     mov    asclseek_high,ax    ; save it
  1022.     mov    asclseek_low,bx     ; both bytes of it
  1023.     cmp    asclseek_method,offset_eof    ; starting from EOF?
  1024.     jne    asclseek_move        ; nope, keep going
  1025.     or    ax,ax            ; yes. Did they give us an offset?
  1026.     jnz    asclseek_bad_off
  1027.     or    bx,bx            ; how about low byte?
  1028.     jz    asclseek_move
  1029.  
  1030. asclseek_bad_off:
  1031.     mov    ax,err_bad_offset    ; set error code
  1032.     jmp    asclseek_ret_bad
  1033.  
  1034. asclseek_move:
  1035.     mov    bx,asclseek_handle    ; get handle
  1036.     mov    cx,asclseek_high    ; get high byte of offset
  1037.     mov    dx,asclseek_low     ; get low byte of offset
  1038.     mov    al,asclseek_method    ; get movement method
  1039.     mov    ah,042h         ; LSEEK
  1040.     int    21h
  1041.  
  1042.     jnc    asclseek_ret_gd
  1043.  
  1044.     add    ax,err_dos_base     ; set DOS error code
  1045.     jmp    asclseek_ret_bad
  1046.  
  1047. asclseek_ret_gd:
  1048.     xor    bx,bx
  1049.     mov    last_ret_cd,ax
  1050.     jmp    short asclseek_ret
  1051.  
  1052. asclseek_ret_bad:
  1053.     mov    last_ret_cd,ax
  1054.     xor    ax,ax
  1055.     dec    ax
  1056.     mov    dx,ax
  1057.     jmp    short asclseek_ret
  1058.  
  1059. asclseek_ret:
  1060.     mov    sp,bp
  1061.     pop    es
  1062.     pop    bp
  1063.     ret_long dx,ax
  1064.     ret
  1065. asclseek    endp
  1066.  
  1067. clipasc ends
  1068.  
  1069.     end
  1070.